
#ifndef SX_PLOT_AXES_ARCHETYPE_H
#define SX_PLOT_AXES_ARCHETYPE_H

#include <sxGeometricObject_Archetype.h>
#include <sxPlotAxes.h>
#include <sxPlotAxes_Representation.h>

/* Archetype classes. */
using Sx::Graphics::Objects::Rendering::RendererImplementation;
using Sx::Graphics::Representations::Objects::PlotAxes_Representation;
using Sx::Graphics::Objects::PlotAxes;

namespace Sx {
namespace Graphics {
namespace Archetypes {
namespace Objects {

class PlotAxes_Archetype : public GeometricObject_Archetype<PlotAxes, float, PlotAxes_Representation> {
public:
	/* Renderer Implementation: Renderer<PlotAxes, PlotAxes_Representation> */
	PlotAxes_Archetype(const std::shared_ptr<RendererImplementation>& renderer);
	PlotAxes_Archetype(const std::shared_ptr<RendererImplementation>& renderer, unsigned int nxTicks, unsigned int pxTicks, unsigned int nyTicks, unsigned int pyTicks, unsigned int nzTicks, unsigned int pzTicks, float tickSpacing = 1.0f);
	virtual ~PlotAxes_Archetype();

	/* 
	 * The physical definition of the plot axes archetype is generated from
	 * abstract definition of the PlotAxes type. In this construct function the
	 * physical representation that is to be rendered is constructed.
	 */
	bool construct();
	void update(float dt) const;

	/* Picking interface */
	bool pick(const Eigen::Vector3f& pickSegmentStart, const Eigen::Vector3f& pickSegmentEnd, Eigen::Vector3f& intersectionPoint);

	/* Intersectable Interface */
	bool intersect(const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segment_p1, Eigen::Vector3f& intersectionPoint);

	bool setXTicks(unsigned int ticks, bool positive);
	bool setYTicks(unsigned int ticks, bool positive);
	bool setZTicks(unsigned int ticks, bool positive);
	bool setGridTicks(unsigned int nxTicks, unsigned int pxTicks, unsigned int nyTicks, unsigned int pyTicks, unsigned int nzTicks, unsigned int pzTicks);

	bool setDisplayX(bool b);
	bool setDisplayY(bool b);
	bool setDisplayZ(bool b);

	bool setDisplayTicks(bool b);
	bool setDisplayTickLabels(bool b);
	bool setDisplayGrid(bool b);
	bool setDisplayGrid(Math::AxisPlane plane, bool b);

protected:
	/*
	 * Stores a grid for each axis plane (xy, yz, xz) in the following format:
	 *   Axes are stored in nx, px, ny, py, nz, pz
	 *   Grid_XY vertices { nxLines, pxLines, nyLines, pyLines }
	 *   Grid_YZ vertices { nyLines, pyLines, nzLines, pzLines }
	 *   Grid_XZ vertices { nxLines, pxLines, nzLines, pzLines } 
	 */
	bool constructUnitPlotAxes();
};

}

}

}

}

#endif
